# -*- coding: utf-8 -*-
import json

import requests
from common.mch import handler as mch_handler
from common.order_inquiry import admin_db as order_inquiry_admin_db
from common.order_inquiry import db as order_inquiry_db
from common.order_inquiry.admin_db import INQUIRY_STATUS, INQUIRY_NOTIFY_STATUS, REASON_FAILURE
from common.utils import exceptions as err
from common.utils import track_logging
from common.utils import tz

_LOGGER = track_logging.getLogger(__name__)

ORDER_INQUIRY_FINISHED = lambda status: status in [INQUIRY_STATUS.SUCCESS, INQUIRY_STATUS.FAILED]
ORDER_INQUIRY_NOT_FINISHED = lambda status: status not in [INQUIRY_STATUS.SUCCESS, INQUIRY_STATUS.FAILED]


def create(params):
    order_inquiry_db.create(params)
    query = get_order_inquiry_by_mch(params['mch_id'], params['order_inquiry_no'], params['out_trade_no'])
    return query


def get_order_inquiry_by_mch(mch_id, order_inquiry_no, out_trade_no):
    order_inquiry = order_inquiry_db.get_order_inquiry_by_mch(mch_id, order_inquiry_no, out_trade_no)

    if not order_inquiry:
        raise err.ResourceNotFound('order_inquiry_no {} not found'.format(order_inquiry_no))

    return {
        'order_inquiry_no': order_inquiry.order_inquiry_no,
        'out_trade_no': order_inquiry.out_trade_no,
        'amount': float(order_inquiry.amount),
        'status_id': order_inquiry.status,
        'status': INQUIRY_STATUS.get_key(order_inquiry.status),
        'reason_failure_id': order_inquiry.reason_failure_id,
        'reason_failure': REASON_FAILURE.get_label(order_inquiry.reason_failure_id) or order_inquiry.reason_failure_desc,
        'updated_at': tz.utc_to_local_str(order_inquiry.updated_at) if order_inquiry.updated_at else None,
        'desc': order_inquiry.inquiry_desc,
    }


def notify(order_inquiry):
    if ORDER_INQUIRY_NOT_FINISHED(order_inquiry.status):
        _LOGGER.info('notify order_inquiry_id {} notify failed order_inquiry.status is {}'.format(order_inquiry.id,
                                                                                                  INQUIRY_STATUS.get_key(
                                                                                                      order_inquiry.status)))
        return

    order_inquiry_info = get_order_inquiry_by_mch(order_inquiry.mch_id, order_inquiry.order_inquiry_no, order_inquiry.out_trade_no)
    calculated_sign = mch_handler.generate_sign(order_inquiry.mch_id, order_inquiry_info)
    order_inquiry_info['sign'] = calculated_sign

    response = requests.post(order_inquiry.notify_url, data=json.dumps(order_inquiry_info), headers={'Content-Type': 'application/json'})

    response_text = response.text.upper() if response.status_code == 200 else 'FAILED'
    status = INQUIRY_NOTIFY_STATUS.get_value(response_text)
    if not status:
        raise err.ResourceNotFound('notify response {} not found'.format(response.text.upper()))

    order_inquiry_admin_db.push_order(order_inquiry.id, status)
    return status


def check_valid_order(order_inquiry, status_func=None, msg=None):
    if order_inquiry and status_func and status_func(order_inquiry.status):
        error = '{} {}'.format(msg, INQUIRY_STATUS.get_key(
            order_inquiry.status)) if msg else 'order_inquiry_no {} is already {}'.format(
            order_inquiry.order_inquiry_no, INQUIRY_STATUS.get_key(order_inquiry.status))
        raise err.DataError(error)

    return True


def json_validator(data):
    try:
        json.loads(data)
        return True, None
    except ValueError as error:
        return False, "invalid json: %s" % error


def check_receipt(data):
    json_result, msg = json_validator(data)
    if not json_result:
        raise err.DataError(msg)

    receipt = json.loads(data)
    if receipt:
        if len(receipt) == 0:
            raise err.DataError('Min receipt is one. Received no receipt.')
    else:
        raise err.DataError('Min receipt is one. Received no receipt.')


def get_receipt(data):
    json_result, _ = json_validator(data)
    if not json_result:
        return None

    receipt = json.loads(data)
    return receipt
